import asyncio
import time
import socket
import threading
from abc import abstractmethod
import logging
from datetime import timedelta
from homeassistant.helpers.event import async_track_time_interval
_LOGGER = logging.getLogger(__name__)
class xkClient():
    """信科客户端"""
    def __init__(self, host, port,hass,lights):
        self.lock = asyncio.Lock()
        data = [ conf['slave'] for conf in lights ]
        self._poll = [ i for n, i in enumerate(data) if i not in data[:n]]
        self._cb = []
        self.host = host
        self.port = port
        self._hass = hass

    async def async_send(self,data):
        try:
            coro = asyncio.open_connection(self.host, self.port)
            reader, writer = await asyncio.wait_for(coro, 1)
        except Exception as e:
            _LOGGER.error("TCP连接失败")
            return 
        writer.write(bytes(data))
        try:
            read = reader.read(40)
            buf = await asyncio.wait_for(read,1)         
            self.onmessage(buf)
        except Exception as e:
            _LOGGER.error('接收超时')
        writer.close()       

    async def req_state(self,slave):
        """请求状态"""
        data = [0x55,slave,0x10,0,0,0,0,0]
        data[-1] = self.data_add(data)
        await self.async_send(data)


    def handle_state(self, data):
        """处理状态"""
        state = []
        bits = data[5]*256+data[6]
        for i in range(16):
            state.append(True if bits >> i & 1 else False)
        if len(self._cb)>0:
            for cb in self._cb:
                cb(state,data[1])

    async def poll_state(self,e):
        for slave in self._poll:
            await self.req_state(slave)
            await asyncio.sleep(0.05)
        

    async def start_hub(self) -> None:
        async_track_time_interval(
                self._hass, self.poll_state, timedelta(seconds=2)
            )

    def add_callback(self,cb):
        self._cb.append(cb)

    async def write_cmd(self,slave,address,cmd):
        """写入命令"""
        data = [0x55,slave,0x11,0,0,0,address,0]
        if cmd:
            data[2] = 0x12
        data[-1] = self.data_add(data)
        await self.async_send(data)

    def onmessage(self, data):
        if not self.check(data):
            """累加校验失败"""
            return False
        if data[0] == 34 and data[2] == 16:  # 状态反馈数据
            self.handle_state(data)

    def check(self, data):
        """累加校验信科"""
        return self.data_add(data) == data[-1]

    def data_add(self,data):
        """累加"""
        sum1 = 0
        for i in range(len(data)-1):
            sum1 = sum1 + data[i]
        return sum1 & 0xff

    
